package battleship_client;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.logging.Level;
import java.util.logging.Logger;
import battleship_admin.*;

/**
 *
 * @author omar
 */
public class FilterManager {

    private Socket socket = null;
    private PrintWriter out = null;
    private BufferedReader in = null;
    private String uniqueConectionID = "";
    private Controller controller;
    public static final String ADDRESS = "127.0.0.1";
    public static final int PORT = 7011;
    private static final int secs = 10;

    public FilterManager(Controller wh) {
        controller = wh;
    }

    public boolean startConnection() throws UnknownHostException, IOException {
        socket = new Socket(ADDRESS, PORT);
        out = new PrintWriter(socket.getOutputStream(), true);
        in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        if (isConnectionActive()) {
            if (uniqueConectionID.equals("")) {
                getUniqueID();
            } else {
                out.println("set-id:");
                out.println(uniqueConectionID);
            }
            return true;
        } else {
            return false;
        }
    }

    private void getUniqueID() {
        try {
            out.println("id-request");
            uniqueConectionID = in.readLine();
        } catch (IOException ex) {
            Logger.getLogger(FilterManager.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public boolean isConnectionActive() {
        return (socket != null && !socket.isClosed() && !pingServer());
    }

    public boolean pingServer() {
        if (in == null) {
            return false;
        }
        PingThread timer = new PingThread(in);
        timer.start();
        out.println("ping");
        long start = System.currentTimeMillis();
        while ((System.currentTimeMillis() - start) / 1000f < secs) {
            if (timer.getPong()) {
                timer = null;
                return true;
            }
        }
        return false;
    }

    public String login(String user, char[] password) {
        try {
            out.println("LOGIN");
            out.println(user);
            for (int i = 0; i < password.length; i++) {
                out.println(password[i]);
            }
            out.println("END_PASSWORD");
            out.println(InetAddress.getLocalHost().getHostAddress());
            return in.readLine();
        } catch (IOException ioe) {
        }
        return "";
    }

    public boolean loginAdmin(String user, char[] password) {
        try {
            out.println("LOGIN_ADMIN");
            out.println(user);
            for (int i = 0; i < password.length; i++) {
                out.println(password[i]);
            }
            out.println("END_PASSWORD");
            if (in.readLine().equals("true")) {
                return true;
            } else {
                return false;
            }
        } catch (IOException io) {
        }
        return false;
    }

    public String createUser(String name, String user, char[] password, String mail) {
        try {
            out.println("CREATE-USER");
            out.println(name);
            out.println(user);
            for (int i = 0; i < password.length; i++) {
                out.println(password[i]);
            }
            out.println("END_PASSWORD");
            out.println(mail);
            out.println(InetAddress.getLocalHost().getHostAddress());
        } catch (IOException e) {
            System.out.println(e.getMessage());
        }
        try {
            String response = in.readLine();
            if (response.equals("true")) {
                return "true";
            } else {
                return in.readLine();
            }
        } catch (IOException ioe) {
            System.out.println(ioe.getMessage());
        }
        return "";
    }

    public void getUserData() {
        out.println("GET-DATA");
        try {
            PlayerDataStruct.setName(in.readLine());
            PlayerDataStruct.setUsername(in.readLine());
            PlayerDataStruct.setPassword(in.readLine());
            PlayerDataStruct.setEmail(in.readLine());
        } catch (IOException ex) {
            Logger.getLogger(FilterManager.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public String getScores() {
        String response = "";
        out.println("GET-SCORES");
        try {
            response = "" + in.readLine();
        } catch (Exception ex) {
            Logger.getLogger(FilterManager.class.getName()).log(Level.SEVERE, null, ex);
        }
        System.out.println(response);
        return response;
    }

    public boolean changeUserData(String name, String user, char[] password, String mail) {
        out.println("CHANGE-DATA");
        out.println(name);
        out.println(user);
        for (int i = 0; i < password.length; i++) {
            out.println(password[i]);
        }
        out.println("END_PASSWORD");
        out.println(mail);
        try {
            return (in.readLine().equals("true"));
        } catch (IOException ioe) {
            System.out.println(ioe.getMessage());
        }
        return false;
    }

    public boolean readyToPlay() {
        out.println("READY");
        try {
            if (in.readLine().equalsIgnoreCase("READY_TO_SET")) {
                return true;
            }
        } catch (IOException ex) {
            Logger.getLogger(FilterManager.class.getName()).log(Level.SEVERE, null, ex);
        }
        return false;
    }

    public boolean selectShips(int[] ships) {
        out.println("SELECT");
        for (int i = 0; i < ships.length; i++) {
            out.println(ships[i]);
        }
        try {
            if (in.readLine().equals("GAME-READY")) {
                return true;
            }
        } catch (IOException ex) {
            Logger.getLogger(FilterManager.class.getName()).log(Level.SEVERE, null, ex);
        }
        return false;
    }

    public void play() {
        try {
            String s = in.readLine();
            System.out.println(s);
            if (s.equalsIgnoreCase("Your turn.")) {
                controller.attack();
            } else if (s.equalsIgnoreCase("Wait")) {
                receiveAttack();
            } else if (s.equals("You won")) {
                controller.finishGame("You won");
            } else if (s.equals("You lost")) {
                controller.finishGame("You lost");
            }
        } catch (IOException ex) {
            Logger.getLogger(FilterManager.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public boolean isSocketActive() {
        try {
            return socket.isConnected();
        } catch (Exception ex) {
            return false;
        }
    }

    public boolean sendAttack(int cx, int cy) {
        try {
            out.println("ATTACK");
            out.println(cx);
            out.println(cy);
            String response = in.readLine();
            return response.equals("Hit");
        } catch (IOException ex) {
            Logger.getLogger(FilterManager.class.getName()).log(Level.SEVERE, null, ex);
        } catch (Exception ex) {
            //en caso de que el socket no se haya inicializado.
        }
        return false;
    }

    public void receiveAttack() {
        try {
            controller.getGameScreen().getLblError().setText("Waiting for opponent's move...");
            controller.getGameScreen().getLblError().setVisible(true);
            String response = in.readLine();
            int x = Integer.parseInt(in.readLine());
            int y = Integer.parseInt(in.readLine());
            controller.receiveAttack(response, x, y);
        } catch (IOException ex) {
            Logger.getLogger(FilterManager.class.getName()).log(Level.SEVERE, null, ex);
        } catch (Exception ex) {
        }
    }

    public void println(String s) {
        out.println(s);
    }

    public String readLine() {
        try {
            return in.readLine();
        } catch (Exception ex) {
            return "";
        }
    }

    public String getOnlineUsers() {
        String respo = "";
        try {
            out.println("GET-USER-NAMES");
            respo = in.readLine();
        } catch (IOException io) {
        }
        return respo;
    }

    public Controller getController() {
        return controller;
    }
}
